grammar ASM74;

@header {
package cpu74;
}

prog
    : line*
    ;

line
    : label COMMENT? EOL
    | label? opcode am COMMENT? EOL
    | label? cmd COMMENT? EOL
    | COMMENT? EOL
    ;

label: ID ':';

opcode
    : 'lda'| 'sta'
    | 'sl' | 'sr'
    | 'add' | 'sub' | 'clc' | 'sec'
    | 'and' | 'or' | 'xor'
    | 'jmp' | 'jnz' | 'jz' | 'jnc' | 'jc'
    | 'stpc'
    ;

am
    : am_default
    | am_imm
    | am_direct
    | am_direct_index
    | am_indirect
    | am_indirect_index
    | am_index_indirect
    ;

am_default          : ;
am_imm              : '#' num;
am_direct           : address;
am_direct_index     : address ',' '#' num;
am_indirect         : '(' address ')';
am_indirect_index   : '(' address ')' ',' '#' num;
am_index_indirect   : '(' address ',' '#' num ')';

cmd
    : '.def' ID expr
    | '.dat' ID NUMBER+
    | '.str' ID STRING
    | '.endproc'
    | '.proc' ID (':' 'near')?
    | '.segment' STRING
    | '.addr' ID
    | '.byte' NUMBER (',' NUMBER)*
    | '.word' NUMBER (',' NUMBER)*
    | '.dword' NUMBER (',' NUMBER)*
    | '.res' NUMBER ',' NUMBER
    | '=' expr
    | 'debug' ID
    ;

expr
    : expr1 (('+'|'-') expr1)*
    ;

expr1
    : expr2 (('*'|'/') expr2)*
    ;

expr2
    : NUMBER
    | ID ('(' expr ')')?
    ;

address : expr;

num     : expr;

ID    : ('_'|'a'..'z' | 'A'..'Z')+ ('_'|'a'..'z' | 'A'..'Z'| '0'..'9')*;

NUMBER
    : '0' [b|B] [0|1]+
    | '0' [x|X] ('a'..'f' | 'A'..'F'| '0'..'9')+
    | '$' ('a'..'f' | 'A'..'F'| '0'..'9')+
    | ('0'..'9')+
    ;

STRING
    : '"' ~ ["]* '"'
    ;

EOL
   : [\r]* [\n]
   ;

//COMMENT
//   : ';' ~ [\r\n]* -> skip
//   ;
COMMENT
   : ';' ~ [\r\n]*
   ;

WS
   : [ \t] -> skip
   ;
